home *** CD-ROM | disk | FTP | other *** search
- Path: xanth!cs.odu.edu!Amiga-Request
- From: Amiga-Request@cs.odu.edu (Amiga Sources/Binaries Moderator)
- Newsgroups: comp.sources.amiga
- Subject: v90i069: Snap 1.4 - cut, store, and paste between windows, Part03/04
- Message-ID: <11377@xanth.cs.odu.edu>
- Date: 11 Feb 90 22:51:09 GMT
- Sender: tadguy@cs.odu.edu
- Reply-To: micke@slaka.sirius.se (Mikael Karlsson)
- Lines: 1836
- Approved: tadguy@cs.odu.edu (Tad Guy)
- X-Mail-Submissions-To: Amiga@cs.odu.edu
- X-Post-Discussions-To: comp.sys.amiga
-
- Submitted-by: micke@slaka.sirius.se (Mikael Karlsson)
- Posting-number: Volume 90, Issue 069
- Archive-name: util/snap-1.4/part03
-
- #!/bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 3 (of 4)."
- # Contents: source/handler.s source/minrexx.c source/snapchars.c
- # Wrapped by tadguy@xanth on Sun Feb 11 17:48:46 1990
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'source/handler.s' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'source/handler.s'\"
- else
- echo shar: Extracting \"'source/handler.s'\" \(17796 characters\)
- sed "s/^X//" >'source/handler.s' <<'END_OF_FILE'
- X include "exec/types.i"
- X include "exec/lists.i"
- X include "devices/inputevent.i"
- X
- Xwaiting equ 0
- Xselregion equ 1
- Xwaitext equ 2
- Xselgfx equ 3
- Xwaitgfx equ 4
- Xinserting equ 5
- Xpendsnap equ 6
- Xkillbutt equ 7
- X
- Xnoaction equ 0
- Xsnapgfx equ 1
- Xsnaptext equ 2
- Xsnapinit equ 3
- Xinsert equ 4
- Xcancel equ 5
- X
- XLMB equ IECODE_LBUTTON
- XLMB_UP equ IECODE_UP_PREFIX+IECODE_LBUTTON
- XRMB equ IECODE_RBUTTON
- XRMB_UP equ IECODE_UP_PREFIX+IECODE_RBUTTON
- XNO_BUTT equ IECODE_NOBUTTON
- XLCOM equ IEQUALIFIER_LCOMMAND
- XSHIFT equ IEQUALIFIER_LSHIFT+IEQUALIFIER_RSHIFT
- X
- X
- X XDEF _myhandler
- X XREF _geta4
- X XREF _LVOSignal
- X XREF _SysBase
- X XREF _MyTask
- X XREF _action
- X XREF _state
- X XREF _modinsert
- X XREF _startsignal
- X XREF _insertsignal
- X XREF _cancelsignal
- X XREF _donesignal
- X XREF _movesignal
- X XREF _clicksignal
- X XREF _timersignal
- X XREF _initsignal
- X XREF _cwsignal
- X XREF _textqual ; qualifier for snapping text
- X XREF _gfxqual ; -"- -"- -"- gfx
- X XREF _insertkey
- X XREF _cwkey
- X
- X SECTION CODE
- X
- X_myhandler:
- X
- X; On entry: a0 : Pointer to event list
- X; a1 : Pointer to data
- X
- X; In loop: a1 : Pointer to event
- X; d0 : scratch
- X
- X; Result: d0 : New event list
- X
- X movem.l a4,-(sp)
- X
- X jsr _geta4 ; Get offset base a4
- X
- X move.l a0,a1 ; a1 = Event list = a0
- X
- X.nextevent
- X cmpa.l #0,a1 ; Check for end of list
- X beq .done
- X
- X cmp.w #noaction,_action ; forced noaction - cancel
- X bne .notcanceled ; no, we're in action
- X move.w #waiting,_state ; no action -> wait state
- X bra .dostate
- X.notcanceled
- X cmp.w #insert,_action ; forced insert - cancel
- X bne .dostate ; no
- X move.w #inserting,_state ; set correct state
- X
- X.dostate
- X move.w _state,d0
- X asl.w #1,d0
- X move.w JumpTable(pc,d0.w),d0
- XOrigin
- X jmp 0(pc,d0.w)
- XJumpTable
- X dc.w .Waiting-Origin-2
- X dc.w .SelRegion-Origin-2
- X dc.w .WaitExt-Origin-2
- X dc.w .SelGfx-Origin-2
- X dc.w .WaitGfx-Origin-2
- X dc.w .Insert-Origin-2
- X dc.w .PendSnap-Origin-2
- X dc.w .CancelTxt-Origin-2
- X
- X; ********************************************************
- X; State: Waiting ~TQ
- X; Actions New state Signal
- X; TQ PendSnap init
- X; LMB+GQ SelGfx init+start
- X; LCOM+IKEY Inserting insert
- X
- X.Waiting
- X cmp.b #IECLASS_RAWKEY,ie_Class(a1) ; Is it RAWKEY?
- X bne .wait_RAWMOUSE
- X
- X move.w ie_Qualifier(a1),d0
- X and.w _textqual,d0 ; TQ?
- X bne .signalinit ; Yes -- init
- X
- X move.w ie_Qualifier(a1),d0
- X and.w #LCOM,d0 ; LCOM?
- X beq .EventHandled ; No
- X
- X move.w _cwkey,d0 ; Control window key
- X cmp.w ie_Code(a1),d0
- X beq .signalcw
- X
- X move.w _insertkey,d0
- X beq .EventHandled ; Key = 0 -- disabled
- X
- X cmp.w ie_Code(a1),d0 ; The insert key?
- X bne .EventHandled ; No, pass it on
- X bra .signalinsert ; Tell'em to insert
- X
- X.wait_RAWMOUSE
- X cmp.b #IECLASS_RAWMOUSE,ie_Class(a1) ; Is it RAWMOUSE?
- X bne .EventHandled ; Nope, pass it on
- X
- X move.w ie_Qualifier(a1),d0
- X and.w _textqual,d0 ; TQ?
- X bne .signalinit ; Yes
- X
- X cmp.w #LMB,ie_Code(a1) ; OK, is it SELECTDOWN?
- X bne .EventHandled ; Too bad
- X
- X move.w ie_Qualifier(a1),d0
- X and.w _gfxqual,d0 ; GQ?
- X beq .EventHandled ; No, not interested
- X
- X; Handle event LMB+GQ
- X move.b #IECLASS_NULL,ie_Class(a1) ; Kill event
- X move.w #snapgfx,_action ; action snapgfx;
- X move.w #selgfx,_state ; state selgfx
- X move.l _initsignal,d0 ; Signal init and
- X or.l _startsignal,d0 ; start
- X bra SignalTask
- X
- X.signalinit
- X move.w #pendsnap,_state
- X move.w #snapinit,_action
- X move.l _initsignal,d0 ; Signal start
- X bsr Signal
- X bra .PendSnap
- X
- X
- X; *******************************************************
- X; State: PendSnap TQ
- X; Actions New state Signal
- X; ~TQ Waiting cancel
- X; LCOM+IKEY Inserting insert
- X; LMB SelRegion start
- X; RMB Inserting insert
- X
- X.PendSnap
- X cmp.b #IECLASS_RAWKEY,ie_Class(a1) ; RAWKEY?
- X bne .ps_RAWMOUSE
- X move.w ie_Qualifier(a1),d0
- X and.w _textqual,d0 ; TQ?
- X bne .ps_IKEY ; Still down, continue
- X
- X;Handle event ~TQ
- X.ps_TQ
- X move.w #noaction,_action ; no action
- X move.w #waiting,_state ; state waiting
- X move.l _cancelsignal,d0 ; snap cancelled
- X bra SignalTask
- X
- X.ps_IKEY
- X move.w ie_Qualifier(a1),d0
- X and.w #LCOM,d0 ; LCOM?
- X beq .EventHandled ; No
- X
- X move.w _cwkey,d0 ; Control window key
- X cmp.w ie_Code(a1),d0
- X beq .signalcw
- X
- X move.w _insertkey,d0
- X beq .EventHandled ; Key = 0 -- disabled
- X
- X cmp.w ie_Code(a1),d0 ; The insert key?
- X bne .EventHandled ; No, pass it on
- X bra .signalinsert ; Tell'em to insert
- X
- X.ps_RAWMOUSE
- X cmp.b #IECLASS_RAWMOUSE,ie_Class(a1) ; Is it RAWMOUSE?
- X bne .EventHandled ; Nope, pass it on
- X
- X move.w ie_Qualifier(a1),d0 ; Might be TQ going up.
- X and.w _textqual,d0 ; TQ?
- X beq .ps_TQ
- X
- X cmp.w #LMB,ie_Code(a1) ; OK, is it SELECTDOWN?
- X bne .ps_RMB ; Too bad
- X
- X; Handle event LMB+TQ
- X move.b #IECLASS_NULL,ie_Class(a1) ; Kill event
- X move.w #snaptext,_action ; action snaptext
- X move.w #selregion,_state ; state selregion
- X move.l _startsignal,d0 ; start
- X bra SignalTask
- X
- X.ps_RMB
- X cmp.w #RMB,ie_Code(a1) ; MENUDOWN
- X bne .EventHandled
- X
- X; Handle event RMB+TQ
- X.signalinsert
- X move.b #IECLASS_NULL,ie_Class(a1) ; Kill event
- X
- X move.w #0,_modinsert
- X move.w ie_Qualifier(a1),d0
- X and.w #SHIFT,d0 ; SHIFT?
- X beq .NonModified ; No
- X move.w #1,_modinsert
- X.NonModified
- X move.w #insert,_action
- X move.w #inserting,_state
- X move.l _insertsignal,d0 ; and insert
- X bra SignalTask
- X
- X.signalcw
- X move.b #IECLASS_NULL,ie_Class(a1) ; Kill event
- X move.w #noaction,_action
- X move.w #waiting,_state
- X move.l _cancelsignal,d0 ; Exit pending snap
- X or.l _cwsignal,d0 ; and tell'em to open window
- X bra SignalTask
- X
- X
- X; *******************************************************
- X; State: SelRegion LMB+TQ
- X; Actions New state Signal
- X; ~TQ Waiting cancel
- X; ~LMB WaitExt
- X; MOVE SelRegion move
- X; RMB SelRegion click
- X; ~RMB SelRegion Needs no action
- X; TIMER SelRegion timer
- X
- X.SelRegion
- X cmp.b #IECLASS_TIMER,ie_Class(a1) ; Timer event?
- X bne .sr_RAWKEY
- X
- X;Handle timer event
- X move.l _timersignal,d0
- X bra SignalTask
- X
- X.sr_RAWKEY
- X cmp.b #IECLASS_RAWKEY,ie_Class(a1) ; RAWKEY?
- X bne .sr_LMB_UP
- X move.b #IECLASS_NULL,ie_Class(a1) ; Kill event
- X move.w ie_Qualifier(a1),d0
- X and.w _textqual,d0 ; TQ?
- X bne .EventHandled ; Still down, continue
- X
- X;Handle event ~TQ
- X.sr_TQ
- X move.w #cancel,_action ; no action
- X move.w #killbutt,_state ; state waiting
- X move.l _cancelsignal,d0 ; snap cancelled
- X bra SignalTask
- X
- X.sr_LMB_UP
- X cmp.b #IECLASS_RAWMOUSE,ie_Class(a1) ; Is it RAWMOUSE?
- X bne .EventHandled ; Nope, pass it on
- X
- X move.w ie_Qualifier(a1),d0 ; Might be TQ going up.
- X and.w _textqual,d0 ; TQ?
- X beq .sr_TQ
- X
- X cmp.w #LMB_UP,ie_Code(a1) ; SELECTUP
- X bne .sr_MOVE ; no, check for move
- X
- X; Handle event ~LMB
- X move.w #waitext,_state ; state waitext
- X bra KillEvent
- X
- X.sr_MOVE
- X cmp.w #NO_BUTT,ie_Code(a1) ; MOVE
- X bne .sr_RMB ; No, check for RMB
- X move.w ie_Qualifier(a1),d0
- X and.w #IEQUALIFIER_RELATIVEMOUSE,d0 ; RELATIVEMOUSE
- X beq .sr_RMB
- X
- X; Handle event MOVE
- X move.l _movesignal,d0
- X bra SignalTask
- X
- X.sr_RMB
- X cmp.w #RMB,ie_Code(a1) ; MENUDOWN
- X bne .EventHandled ; No, not interested
- X
- X; Handle event RMB
- X move.b #IECLASS_NULL,ie_Class(a1) ; Kill event
- X move.l _clicksignal,d0
- X bra SignalTask
- X
- X; ***************************************************
- X; State WaitExt TQ
- X; Actions New state Signal
- X; ~TQ Waiting done
- X; LMB SelRegion click
- X; MOVE WaitExt No action needed.
- X; RMB Inserting done & insert
- X; TIMER WaitExt timer
- X
- X.WaitExt
- X cmp.b #IECLASS_TIMER,ie_Class(a1) ; Timer event?
- X bne .we_RAWKEY
- X
- X;Handle timer event
- X move.l _timersignal,d0
- X bra SignalTask
- X
- X.we_RAWKEY
- X cmp.b #IECLASS_RAWKEY,ie_Class(a1) ; RAWKEY?
- X bne .we_LMB
- X move.b #IECLASS_NULL,ie_Class(a1) ; Kill event
- X move.w ie_Qualifier(a1),d0
- X and.w _textqual,d0 ; TQ?
- X bne .EventHandled ; Still down, continue
- X
- X;Handle event ~TQ
- X.we_TQ
- X move.w #noaction,_action ; no action
- X move.w #waiting,_state ; state waiting
- X move.l _donesignal,d0 ; snap finished
- X bra SignalTask
- X
- X.we_LMB
- X cmp.b #IECLASS_RAWMOUSE,ie_Class(a1) ; Is it RAWMOUSE?
- X bne .EventHandled ; Nope, pass it on
- X
- X move.w ie_Qualifier(a1),d0 ; Might be TQ going up.
- X and.w _textqual,d0 ; TQ?
- X beq .we_TQ ; No.
- X
- X cmp.w #LMB,ie_Code(a1) ; SELECTDOWN
- X bne .we_RMB ; no, check for RMB
- X
- X; Handle event LMB
- X move.b #IECLASS_NULL,ie_Class(a1) ; Kill event
- X move.w #selregion,_state ; state waitext
- X move.l _clicksignal,d0 ; Extend selection
- X bra SignalTask
- X
- X.we_RMB
- X cmp.w #RMB,ie_Code(a1) ; MENUDOWN
- X bne .EventHandled ; No, not interested
- X
- X; Handle event RMB
- X move.b #IECLASS_NULL,ie_Class(a1) ; Kill event
- X move.w #insert,_action
- X move.w #inserting,_state
- X move.l _donesignal,d0
- X or.l _insertsignal,d0
- X bra SignalTask
- X
- X; *******************************************************
- X; State: SelGfx LMB+GQ
- X; Actions New state Signal
- X; ~GQ Waiting cancel
- X; ~LMB WaitGfx
- X; MOVE SelGfx move
- X; TIMER SelGfx timer
- X; RMB SelGfx removed
- X
- X.SelGfx
- X cmp.b #IECLASS_TIMER,ie_Class(a1) ; Timer event?
- X bne .sg_RAWKEY
- X
- X;Handle timer event
- X move.l _timersignal,d0
- X bra SignalTask
- X
- X.sg_RAWKEY
- X cmp.b #IECLASS_RAWKEY,ie_Class(a1) ; RAWKEY?
- X bne .sg_LMB_UP
- X move.b #IECLASS_NULL,ie_Class(a1) ; Kill event
- X move.w ie_Qualifier(a1),d0
- X and.w _gfxqual,d0 ; GQ?
- X bne .EventHandled ; Still down, continue
- X
- X;Handle event ~GQ
- X.sg_GQ
- X move.w #cancel,_action ; cancelling snap
- X move.w #killbutt,_state ; Kill obsolete button
- X move.l _cancelsignal,d0 ; snap cancelled
- X bra SignalTask
- X
- X.sg_LMB_UP
- X cmp.b #IECLASS_RAWMOUSE,ie_Class(a1) ; Is it RAWMOUSE?
- X bne .EventHandled ; Nope, pass it on
- X
- X move.w ie_Qualifier(a1),d0 ; Might be GQ going up.
- X and.w _gfxqual,d0 ; GQ?
- X beq .sg_GQ
- X
- X cmp.w #LMB_UP,ie_Code(a1) ; SELECTUP
- X bne .sg_MOVE ; no, check for move
- X
- X; Handle event ~LMB
- X move.w #waitgfx,_state ; state waitext
- X bra KillEvent
- X
- X.sg_MOVE
- X cmp.w #NO_BUTT,ie_Code(a1) ; MOVE
- X bne .EventHandled ; No, check for RMB
- X move.w ie_Qualifier(a1),d0
- X and.w #IEQUALIFIER_RELATIVEMOUSE,d0 ; RELATIVEMOUSE
- X beq .EventHandled
- X
- X; Handle event MOVE
- X move.l _movesignal,d0
- X bra SignalTask
- X
- X.sg_RMB
- X bra KillEvent
- X
- X; ***************************************************
- X; State WaitGfx GQ
- X; Actions New state Signal
- X; ~GQ Waiting done
- X; LMB SelGfx click
- X; MOVE WaitGfx No action needed.
- X; TIMER WaitGfx timer
- X; RMB WaitGfx -- remove event
- X
- X.WaitGfx
- X cmp.b #IECLASS_TIMER,ie_Class(a1) ; Timer event?
- X bne .wg_RAWKEY
- X
- X;Handle timer event
- X move.l _timersignal,d0
- X bra SignalTask
- X
- X.wg_RAWKEY
- X cmp.b #IECLASS_RAWKEY,ie_Class(a1) ; RAWKEY?
- X bne .wg_LMB
- X move.b #IECLASS_NULL,ie_Class(a1) ; Kill event
- X move.w ie_Qualifier(a1),d0
- X and.w _gfxqual,d0 ; GQ?
- X bne .EventHandled ; Still down, continue
- X
- X;Handle event ~GQ
- X.wg_GQ
- X move.w #noaction,_action ; no action
- X move.w #waiting,_state ; state waiting
- X move.l _donesignal,d0 ; snap finished
- X bra SignalTask
- X
- X.wg_LMB
- X cmp.b #IECLASS_RAWMOUSE,ie_Class(a1) ; Is it RAWMOUSE?
- X bne .EventHandled ; Nope, pass it on
- X
- X move.w ie_Qualifier(a1),d0 ; Might be GQ going up
- X and.w _gfxqual,d0 ; GQ?
- X beq .wg_GQ
- X
- X cmp.w #LMB,ie_Code(a1) ; SELECTDOWN
- X bne .wg_RMB ; no -- finished
- X
- X; Handle event LMB
- X move.b #IECLASS_NULL,ie_Class(a1) ; Kill event
- X move.w #selgfx,_state ; state waitext
- X move.l _clicksignal,d0 ; Extend selection
- X bra SignalTask
- X
- X.wg_RMB
- X cmp.w #NO_BUTT,ie_Code(a1) ; Any button?
- X beq .EventHandled ; No, moves are ok
- X
- X bra KillEvent
- X
- X
- X; ***************************************************
- X; State CancelTxt
- X; Make sure that the Button Up event that we've got
- X; hanging around doesn't get through.
- X
- X.CancelTxt
- X cmp.b #IECLASS_RAWMOUSE,ie_Class(a1) ; Is it RAWMOUSE?
- X bne .EventHandled ; Nope, just pass it on
- X
- X cmp.w #LMB_UP,ie_Code(a1) ; The button?
- X bne .EventHandled ; No
- X
- X move.w #noaction,_action
- X move.w #waiting,_state
- X bra KillEvent
- X
- X; ***************************************************
- X; State Insert
- X; Snap actions are removed, the rest are passed along.
- X
- X.Insert
- X cmp.b #IECLASS_RAWMOUSE,ie_Class(a1) ; Is it RAWMOUSE?
- X bne .EventHandled ; Nope, pass it on
- X
- X cmp.w #LMB,ie_Code(a1) ; Left mouse button
- X bne .insert_TQ ; No -- just kill
- X
- X move.w #noaction,_action ; Cancel paste
- X
- X.insert_TQ
- X move.w ie_Qualifier(a1),d0
- X and.w _textqual,d0 ; TQ?
- X beq .EventHandled ; no
- X
- X cmp.w #NO_BUTT,ie_Code(a1) ; Any button?
- X beq .EventHandled ; No, moves are ok
- X
- XKillEvent:
- X move.b #IECLASS_NULL,ie_Class(a1) ; Kill event
- X bra .EventHandled
- X
- XSignalTask:
- X bsr Signal
- X
- X.EventHandled
- X move.l ie_NextEvent(a1),a1 ; Get next event
- X bra .nextevent
- X
- X.done
- X movem.l (sp)+,a4
- X move.l a0,d0
- X rts
- X
- XSignal:
- X movem.l a0-a2/a6,-(sp)
- X move.l _MyTask,a1
- X move.l _SysBase,a6 ; Get ExecBase for Signal
- X jsr _LVOSignal(a6)
- X movem.l (sp)+,a0-a2/a6
- X rts
- X
- X end
- END_OF_FILE
- if test 17796 -ne `wc -c <'source/handler.s'`; then
- echo shar: \"'source/handler.s'\" unpacked with wrong size!
- fi
- # end of 'source/handler.s'
- fi
- if test -f 'source/minrexx.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'source/minrexx.c'\"
- else
- echo shar: Extracting \"'source/minrexx.c'\" \(15411 characters\)
- sed "s/^X//" >'source/minrexx.c' <<'END_OF_FILE'
- X#ifdef SNAPREXX
- X/*
- X * This is an example of how REXX messages might be handled. This is
- X * a `minimum' example that both accepts asynchronous REXX messages and
- X * can request REXX service.
- X *
- X * Read this entire file! It's short enough.
- X *
- X * It is written in such a fashion that it can be attached to a program
- X * with a minimum of fuss. The only external symbols it makes available
- X * are the seven functions and RexxSysBase.
- X *
- X * This code is by Radical Eye Software, but it is put in the public
- X * domain. I would appreciate it if the following string was left in
- X * both as a version check and as thanks from you for the use of this
- X * code.
- X *
- X * If you modify this file for your own use, don't bump the version
- X * number; add a suffix, such as 1.0a or 1.0.3 or something, so we
- X * don't have fake `versions' floating around.
- X */
- Xstatic char *blurb = "Radical Eye MinRexx 0.4" ;
- X/*
- X * We read in our own personal little include.
- X */
- X#include "minrexx.h"
- X/*
- X * All of our local globals, hidden from sight.
- X */
- Xstatic struct MsgPort *rexxPort ; /* this is *our* rexx port */
- Xstatic int bringerdown ; /* are we trying to shut down? */
- Xstatic struct rexxCommandList *globalrcl ; /* our command association list */
- Xstatic long stillNeedReplies ; /* how many replies are pending? */
- Xstatic long rexxPortBit ; /* what bit to wait on for Rexx? */
- Xstatic char *extension ; /* the extension for macros */
- Xstatic int (*userdisp)() ; /* the user's dispatch function */
- Xstatic struct RexxMsg *oRexxMsg ; /* the outstanding Rexx message */
- X/*
- X * Our library base. Don't you dare close this!
- X */
- Xstruct RxsLib *RexxSysBase ;
- X/*
- X * This is the main entry point into this code.
- X */
- Xlong upRexxPort(s, rcl, exten, uf)
- X/*
- X * The first argument is the name of your port to be registered;
- X * this will be used, for instance, with the `address' command of ARexx.
- X */
- Xchar *s ;
- X/*
- X * The second argument is an association list of command-name/user-data
- X * pairs. It's an array of struct rexxCommandList, terminated by a
- X * structure with a NULL in the name field. The commands are case
- X * sensitive. The user-data field can contain anything appropriate,
- X * perhaps a function to call or some other data.
- X */
- Xstruct rexxCommandList *rcl ;
- X/*
- X * The third argument is the file extension for ARexx macros invoked
- X * by this program. If you supply this argument, any `primitive' not
- X * in the association list rcl will be sent out to ARexx for
- X * interpretation, thus allowing macro programs to work just like
- X * primitives. If you do not want this behavior, supply a `NULL'
- X * here, and those commands not understood will be replied with an
- X * error value of RXERRORNOCMD.
- X */
- Xchar *exten ;
- X/*
- X * The fourth argument is the user dispatch function. This function
- X * will *only* be called from rexxDisp(), either from the user calling
- X * this function directly, or from dnRexxPort(). Anytime a command
- X * match is found in the association list, this user-supplied function
- X * will be called with two arguments---the Rexx message that was
- X * received, and a pointer to the association pair. This function
- X * should return a `1' if the message was replied to by the function
- X * and a `0' if the default success code of (0, 0) should be returned.
- X * Note that the user function should never ReplyMsg() the message;
- X * instead he should indicate the return values with replyRexxCmd();
- X * otherwise we lose track of the messages that still lack replies.
- X */
- Xint (*uf)() ;
- X/*
- X * upRexxPort() returns the signal bit to wait on for Rexx messages.
- X * If something goes wrong, it simply returns a `0'. Note that this
- X * function is safe to call multiple times because we check to make
- X * sure we haven't opened already. It's also a quick way to change
- X * the association list or dispatch function.
- X */
- X{
- X struct MsgPort *FindPort() ;
- X struct MsgPort *CreatePort() ;
- X
- X/*
- X * Some basic error checking.
- X */
- X if (rcl == NULL || uf == NULL)
- X return(0L) ;
- X/*
- X * If we aren't open, we make sure no one else has opened a port with
- X * this name already. If that works, and the createport succeeds, we
- X * fill rexxPortBit with the value to return.
- X *
- X * Note that rexxPortBit will be 0 iff rexxPort is NULL, so the check
- X * for rexxPort == NULL also insures that our rexxPortBit is 0.
- X */
- X if (rexxPort == NULL) {
- X Forbid() ;
- X if (FindPort(s)==NULL)
- X rexxPort = CreatePort(s, 0L) ;
- X Permit() ;
- X if (rexxPort != NULL)
- X rexxPortBit = 1L << rexxPort->mp_SigBit ;
- X }
- X/*
- X * Squirrel away these values for our own internal access, and return
- X * the wait bit.
- X */
- X globalrcl = rcl ;
- X extension = exten ;
- X userdisp = uf ;
- X return(rexxPortBit) ;
- X}
- X/*
- X * This function closes the rexx library, but only if it is open
- X * and we aren't expecting further replies from REXX. It's
- X * *private*, but it doesn't have to be; it's pretty safe to
- X * call anytime.
- X */
- Xstatic void closeRexxLib() {
- X if (stillNeedReplies == 0 && RexxSysBase) {
- X CloseLibrary(RexxSysBase) ;
- X RexxSysBase = NULL ;
- X }
- X}
- X/*
- X * This function closes down the Rexx port. It is always safe to
- X * call, and should *definitely* be made a part of your cleanup
- X * routine. No arguments and no return. It removes the Rexx port,
- X * replies to all of the messages and insures that we get replies
- X * to all the ones we sent out, closes the Rexx library, deletes the
- X * port, clears a few flags, and leaves.
- X */
- Xvoid dnRexxPort() {
- X if (rexxPort) {
- X RemPort(rexxPort) ;
- X bringerdown = 1 ;
- X/*
- X * A message still hanging around? We kill it off.
- X */
- X if (oRexxMsg) {
- X oRexxMsg->rm_Result1 = RXERRORIMGONE ;
- X ReplyMsg(oRexxMsg) ;
- X oRexxMsg = NULL ;
- X }
- X while (stillNeedReplies) {
- X WaitPort(rexxPort) ;
- X dispRexxPort() ;
- X }
- X closeRexxLib() ;
- X DeletePort(rexxPort) ;
- X rexxPort = NULL ;
- X }
- X rexxPortBit = 0 ;
- X}
- X/*
- X * Here we dispatch any REXX messages that might be outstanding.
- X * This is the main routine for handling Rexx messages.
- X * This function is fast if no messages are outstanding, so it's
- X * pretty safe to call fairly often.
- X *
- X * If we are bring the system down and flushing messages, we reply
- X * with a pretty serious return code RXERRORIMGONE.
- X *
- X * No arguments, no returns.
- X */
- Xvoid dispRexxPort() {
- X register struct RexxMsg *RexxMsg ;
- X int cmdcmp() ;
- X register struct rexxCommandList *rcl ;
- X register char *p ;
- X register int dontreply ;
- X
- X/*
- X * If there's no rexx port, we're out of here.
- X */
- X if (rexxPort == NULL)
- X return ;
- X/*
- X * Otherwise we have our normal loop on messages.
- X */
- X while (RexxMsg = (struct RexxMsg *)GetMsg(rexxPort)) {
- X/*
- X * If we have a reply to a message we sent, we look at the second
- X * argument. If it's set, it's a function we are supposed to call
- X * so we call it. Then, we kill the argstring and the message
- X * itself, decrement the outstanding count, and attempt to close
- X * down the Rexx library. Note that this call only succeeds if
- X * there are no outstanding messages. Also, it's pretty quick, so
- X * don't talk to me about efficiency.
- X */
- X if (RexxMsg->rm_Node.mn_Node.ln_Type == NT_REPLYMSG) {
- X if (RexxMsg->rm_Args[1]) {
- X ((int (*)())(RexxMsg->rm_Args[1]))(RexxMsg) ;
- X }
- X DeleteArgstring(RexxMsg->rm_Args[0]) ;
- X DeleteRexxMsg(RexxMsg) ;
- X stillNeedReplies-- ;
- X closeRexxLib() ;
- X/*
- X * The default case is we got a message and we need to check it for
- X * primitives. We skip past any initial tabs or spaces and initialize
- X * the return code fields.
- X */
- X } else {
- X p = (char *)RexxMsg->rm_Args[0] ;
- X while (*p > 0 && *p <= ' ')
- X p++ ;
- X RexxMsg->rm_Result1 = 0 ;
- X RexxMsg->rm_Result2 = 0 ;
- X/*
- X * If somehow the reply is already done or postponed, `dontreply' is
- X * set.
- X */
- X dontreply = 0 ;
- X/*
- X * If the sky is falling, we just blow up and replymsg.
- X */
- X if (bringerdown) {
- X RexxMsg->rm_Result1 = RXERRORIMGONE ;
- X/*
- X * Otherwise we cdr down our association list, comparing commands,
- X * until we get a match. If we get a match, we call the dispatch
- X * function with the appropriate arguments, and break out.
- X */
- X } else {
- X oRexxMsg = RexxMsg ;
- X for (rcl = globalrcl; rcl->name; rcl++) {
- X if (cmdcmp(rcl->name, p) == 0) {
- X userdisp(RexxMsg, rcl, p+strlen(rcl->name)) ;
- X break ;
- X }
- X }
- X/*
- X * If we broke out, rcl will point to the command we executed; if we
- X * are at the end of the list, we didn't understand the command. In
- X * this case, if we were supplied an extension in upRexxPort, we know
- X * that we should send the command out, so we do so, synchronously.
- X * The synchronous send takes care of our reply. If we were given a
- X * NULL extension, we bitch that the command didn't make sense to us.
- X */
- X if (rcl->name == NULL) {
- X if (extension) {
- X syncRexxCmd(RexxMsg->rm_Args[0], RexxMsg) ;
- X dontreply = 1 ;
- X } else {
- X RexxMsg->rm_Result1 = RXERRORNOCMD ;
- X }
- X }
- X }
- X/*
- X * Finally, reply if appropriate.
- X */
- X oRexxMsg = NULL ;
- X if (! dontreply)
- X ReplyMsg(RexxMsg) ;
- X }
- X }
- X}
- X/*
- X * This is the function we use to see if the command matches
- X * the command string. Not case sensitive, and the real command only
- X * need be a prefix of the command string. Make sure all commands
- X * are given in lower case!
- X */
- Xstatic int cmdcmp(c, m)
- Xregister char *c, *m ;
- X{
- X while (*c && ((*c == *m) || (*c == *m + 32 && ('a' <= *c && *c <= 'z')))) {
- X c++ ;
- X m++ ;
- X }
- X return(*c) ;
- X}
- X/*
- X * Opens the Rexx library if unopened. Returns success (1) or
- X * failure (0). This is another function that is *private* but
- X * that doesn't have to be.
- X */
- Xstatic int openRexxLib() {
- X if (RexxSysBase)
- X return(1) ;
- X return((RexxSysBase = (struct RxsLib *)OpenLibrary(RXSNAME, 0L)) != NULL) ;
- X}
- X/*
- X * This is the general ARexx command interface, but is not the one
- X * you will use most of the time; ones defined later are easier to
- X * understand and use. But they all go through here.
- X */
- Xstruct RexxMsg *sendRexxCmd(s, f, p1, p2, p3)
- Xchar *s ;
- X/*
- X * The first parameter is the command to send to Rexx.
- X */
- Xint (*f)() ;
- X/*
- X * The second parameter is either NULL, indicating that the command
- X * should execute asynchronously, or a function to be called when the
- X * message we build up and send out here finally returns. Please note
- X * that the function supplied here could be called during cleanup after
- X * a fatal error, so make sure it is `safe'. This function always is
- X * passed one argument, the RexxMsg that is being replied.
- X */
- XSTRPTR p1, p2, p3 ;
- X/*
- X * These are up to three arguments to be stuffed into the RexxMsg we
- X * are building up, making the values available when the message is
- X * finally replied to. The values are stuffed into Args[2]..Args[4].
- X */
- X{
- X struct RexxMsg *CreateRexxMsg() ;
- X STRPTR CreateArgstring() ;
- X register struct MsgPort *rexxport ;
- X register struct RexxMsg *RexxMsg ;
- X
- X/*
- X * If we have too many replies out there, we just return failure.
- X * Note that you should check the return code to make sure your
- X * message got out! Then, we forbid, and make sure that:
- X * - we have a rexx port open
- X * - Rexx is out there
- X * - the library is open
- X * - we can create a message
- X * - we can create an argstring
- X *
- X * If all of these succeed, we stuff a few values and send the
- X * message, permit, and return.
- X */
- X if (rexxPort == NULL || stillNeedReplies > MAXRXOUTSTANDING-1)
- X return(NULL) ;
- X RexxMsg = NULL ;
- X if (openRexxLib() && (RexxMsg =
- X CreateRexxMsg(rexxPort, extension, rexxPort->mp_Node.ln_Name)) &&
- X (RexxMsg->rm_Args[0] = CreateArgstring(s, (long)strlen(s)))) {
- X RexxMsg->rm_Action = RXCOMM ;
- X RexxMsg->rm_Args[1] = (STRPTR)f ;
- X RexxMsg->rm_Args[2] = p1 ;
- X RexxMsg->rm_Args[3] = p2 ;
- X RexxMsg->rm_Args[4] = p3 ;
- X RexxMsg->rm_Node.mn_Node.ln_Name = RXSDIR ;
- X Forbid() ;
- X if (rexxport = FindPort(RXSDIR))
- X PutMsg(rexxport, RexxMsg) ;
- X Permit() ;
- X if (rexxport) {
- X stillNeedReplies++ ;
- X return(RexxMsg) ;
- X } else
- X DeleteArgstring(RexxMsg->rm_Args[0]) ;
- X }
- X if (RexxMsg)
- X DeleteRexxMsg(RexxMsg) ;
- X closeRexxLib() ;
- X return(NULL) ;
- X}
- X/*
- X * This function is used to send out an ARexx message and return
- X * immediately. Its single parameter is the command to send.
- X */
- Xstruct RexxMsg *asyncRexxCmd(s)
- Xchar *s ;
- X{
- X return(sendRexxCmd(s, NULL, NULL, NULL, NULL)) ;
- X}
- X/*
- X * This function sets things up to reply to the message that caused
- X * it when we get a reply to the message we are sending out here.
- X * But first the function we pass in, which actually handles the reply.
- X * Note how we get the message from the Args[2]; Args[0] is the command,
- X * Args[1] is this function, and Args[2]..Args[4] are any parameters
- X * passed to sendRexxCmd() as p1..p3. We pass the result codes right
- X * along.
- X */
- Xstatic void replytoit(msg)
- Xregister struct RexxMsg *msg ;
- X{
- X register struct RexxMsg *omsg ;
- X
- X omsg = (struct RexxMsg *)(msg->rm_Args[2]) ;
- X replyRexxCmd(omsg, msg->rm_Result1, msg->rm_Result2, NULL) ;
- X ReplyMsg(omsg) ;
- X}
- X/*
- X * This function makes use of everything we've put together so far,
- X * and functions as a synchronous Rexx call; as soon as the macro
- X * invoked here returns, we reply to `msg', passing the return codes
- X * back.
- X */
- Xstruct RexxMsg *syncRexxCmd(s, msg)
- Xchar *s ;
- Xstruct RexxMsg *msg ;
- X{
- X return(sendRexxCmd(s, (APTR)&replytoit, msg, NULL, NULL)) ;
- X}
- X/*
- X * There are times when you want to pass back return codes or a
- X * return string; call this function when you want to do that,
- X * and return `1' from the user dispatch function so the main
- X * event loop doesn't reply (because we reply here.) This function
- X * always returns 1.
- X */
- Xvoid replyRexxCmd(msg, primary, secondary, string)
- X/*
- X * The first parameter is the message we are replying to.
- X */
- Xregister struct RexxMsg *msg ;
- X/*
- X * The next two parameters are the primary and secondary return
- X * codes.
- X */
- Xregister long primary, secondary ;
- X/*
- X * The final parameter is a return string. This string is only
- X * returned if the primary return code is 0, and a string was
- X * requested.
- X *
- X * We also note that we have replied to the message that came in.
- X */
- Xregister char *string ;
- X{
- X STRPTR CreateArgstring() ;
- X
- X/*
- X * Note how we make sure the Rexx Library is open before calling
- X * CreateArgstring . . . and we close it down at the end, if possible.
- X */
- X if (primary == 0 && (msg->rm_Action & (1L << RXFB_RESULT))) {
- X if (string && openRexxLib())
- X secondary = (long)CreateArgstring(string, (long)strlen(string)) ;
- X else
- X secondary = 0L ;
- X }
- X msg->rm_Result1 = primary ;
- X msg->rm_Result2 = secondary ;
- X closeRexxLib() ;
- X}
- X#endif
- END_OF_FILE
- if test 15411 -ne `wc -c <'source/minrexx.c'`; then
- echo shar: \"'source/minrexx.c'\" unpacked with wrong size!
- fi
- # end of 'source/minrexx.c'
- fi
- if test -f 'source/snapchars.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'source/snapchars.c'\"
- else
- echo shar: Extracting \"'source/snapchars.c'\" \(21526 characters\)
- sed "s/^X//" >'source/snapchars.c' <<'END_OF_FILE'
- X/* Auto: make
- X*/
- X
- XIMPORT struct SnapRsrc *SnapRsrc;
- X
- X#define COPY 0xC0L
- X#define INVCOPY 0x30L
- X#define CopyChar(_x, _y, _m) \
- X BltBitMap(&MyBM, (LONG)_x, (LONG)_y, \
- X &TempBM, 0L, 0L, (LONG)FontWidth, (LONG)FontHeight, \
- X _m, -1L, NULL); \
- X WaitBlit()
- X
- XWORD Unit;
- XWORD Pattern[5] = {
- X 0,
- X 0x0c3f, /* Frame ....oo....oooooo */
- X 0x3333, /* Char ..oo..oo..oo..oo */
- X 0x1f1f, /* Word ...ooooo...ooooo */
- X 0xffff /* Line oooooooooooooooo */
- X};
- X
- XIMPORT LONG xl; /* leftmost x position */
- XIMPORT LONG xr; /* rightmost x position */
- XIMPORT LONG yt; /* topmost y position */
- XIMPORT LONG yb; /* bottommost y position */
- XLONG minx; /* left limit */
- XLONG maxx; /* right limit */
- XLONG maxy; /* bottom limit */
- XLONG tl, tr; /* used by findword - left and right edge of word */
- XWORD fw, fh; /* Font width and height used when drawing the frame */
- XWORD GZZ;
- XWORD SBM;
- X
- XIMPORT LONG mx, my; /* Mouse position in character steps */
- X#define closetop 0
- X#define closebottom 1
- XWORD closey;
- X#define closeleft 0
- X#define closeright 1
- XWORD closex;
- X
- X
- Xstruct Window *window; /* The window we're snapping from */
- X
- X/* Data for font being snapped */
- XUWORD FontHeight;
- XUWORD FontWidth;
- XUWORD Underscore;
- XUBYTE FontType;
- XUBYTE LoChar;
- XUBYTE HiChar;
- XUWORD Modulo;
- XUWORD *CharLoc;
- XUWORD NoOfChars;
- XUBYTE *SrcData;
- XIMPORT UBYTE *CharData;
- XUBYTE IFlags;
- X
- XIMPORT struct RastPort TempRp, MyRP;
- XIMPORT struct BitMap TempBM, MyBM;
- X
- XIMPORT UWORD *TempRaster; /* Used for character recognition */
- X
- XIMPORT struct Screen *theScreen;
- XIMPORT struct RastPort rp;
- Xstruct Layer *LockedLayer;
- X
- XIMPORT LONGBITS cancelsignal, donesignal, movesignal, clicksignal, timersignal;
- XIMPORT WORD action;
- X
- XWORD starting;
- X
- X/* Init vars with font data.
- X*/
- X
- XVOID SetSnapFont(font)
- Xstruct TextFont *font;
- X{
- X if (!font) {
- X FontWidth = -1;
- X return;
- X }
- X FontHeight = font->tf_YSize;
- X Underscore = font->tf_Baseline + 1;
- X FontType = font->tf_Flags;
- X FontWidth = (FontType & FPF_PROPORTIONAL ? -1 : font->tf_XSize);
- X if (FontWidth == -1) {
- X return;
- X }
- X LoChar = font->tf_LoChar;
- X HiChar = font->tf_HiChar;
- X Modulo = font->tf_Modulo;
- X CharLoc = (UWORD *)font->tf_CharLoc;
- X NoOfChars = HiChar - LoChar + 1;
- X Modulo = font->tf_Modulo;
- X SrcData = (UBYTE *)font->tf_CharData;
- X BltClear(CharData, 256L * 32, 0L);
- X WaitBlit();
- X CopyFont();
- X}
- X
- X/* Check if the character at x, y is a space
- X*/
- X
- XWORD IsSpace(x, y)
- XLONG x, y;
- X{
- X REGISTER WORD i = FontHeight - 1;
- X REGISTER UWORD *data = &TempRaster[i];
- X
- X /* Copy character at x, y */
- X BltClear((char *)TempRaster, 32L, 0L);
- X ClipBlit(&rp, x, y,
- X &TempRp, 0L, 0L, (LONG)FontWidth, (LONG)FontHeight, COPY);
- X WaitBlit();
- X
- X if (*data) { /* Try inverted copy */
- X ClipBlit(&rp, x, y,
- X &TempRp, 0L, 0L, (LONG)FontWidth, (LONG)FontHeight, INVCOPY);
- X WaitBlit();
- X }
- X while (i--) {
- X if (*data--) {
- X return 0;
- X }
- X }
- X return 1;
- X}
- X
- X#define ShortFrame 4L /* Square frame - columnar select */
- X#define LongFrame 8L /* Strange frame - char or word select */
- XIMPORT LONG OFType; /* Old frame type: ShortFrame/LongFrame */
- XIMPORT UWORD Ptrn;
- XIMPORT Point OldFrame[];
- XIMPORT Point NewFrame[];
- X
- X
- X/* update_frame calculates the new frame,
- X** erases the old frame and draws the new one.
- X** It's all pretty obvious if you take it slowly.
- X*/
- XVOID update_frame()
- X{
- X LONG ft;
- X switch (Unit) {
- X case UNIT_FRAME: {
- X /*********\
- X * *
- X * *
- X \*********/
- X NewFrame[0].x = xl - 1; NewFrame[0].y = yt - 1;
- X NewFrame[1].x = xr + fw; NewFrame[1].y = yt - 1;
- X NewFrame[2].x = xr + fw; NewFrame[2].y = yb + fh;
- X NewFrame[3].x = xl - 1; NewFrame[3].y = yb + fh;
- X NewFrame[4].x = xl - 1; NewFrame[4].y = yt - 1;
- X ft = ShortFrame;
- X break;
- X }
- X case UNIT_CHAR:
- X case UNIT_WORD: {
- X if (yt == yb) { /* On the same line - same as UNIT_FRAME */
- X NewFrame[0].x = xl - 1; NewFrame[0].y = yt - 1;
- X NewFrame[1].x = xr + fw; NewFrame[1].y = yt - 1;
- X NewFrame[2].x = xr + fw; NewFrame[2].y = yb + fh;
- X NewFrame[3].x = xl - 1; NewFrame[3].y = yb + fh;
- X NewFrame[4].x = xl - 1; NewFrame[4].y = yt - 1;
- X ft = ShortFrame;
- X } else {
- X /*****\
- X ****** *
- X * *
- X * *****
- X *******/
- X NewFrame[0].x = xl - 1; NewFrame[0].y = yt - 1;
- X NewFrame[1].x = maxx + fw; NewFrame[1].y = yt - 1;
- X NewFrame[2].x = maxx + fw; NewFrame[2].y = yb;
- X NewFrame[3].x = xr + fw; NewFrame[3].y = yb;
- X NewFrame[4].x = xr + fw; NewFrame[4].y = yb + fh;
- X NewFrame[5].x = minx - 1; NewFrame[5].y = yb + fh;
- X NewFrame[6].x = minx - 1; NewFrame[6].y = yt + fh;
- X NewFrame[7].x = xl - 1; NewFrame[7].y = yt + fh;
- X NewFrame[8].x = xl - 1; NewFrame[8].y = yt - 1;
- X ft = LongFrame;
- X }
- X break;
- X }
- X case UNIT_LINE: {
- X NewFrame[0].x = minx - 1; NewFrame[0].y = yt - 1;
- X NewFrame[1].x = maxx + fw; NewFrame[1].y = yt - 1;
- X NewFrame[2].x = maxx + fw; NewFrame[2].y = yb + fh;
- X NewFrame[3].x = minx - 1; NewFrame[3].y = yb + fh;
- X NewFrame[4].x = minx - 1; NewFrame[4].y = yt - 1;
- X ft = ShortFrame;
- X break;
- X }
- X default: {
- X break;
- X }
- X }
- X draw_frame(ft);
- X}
- X
- XVOID FindWord()
- X{
- X /* Must remove frame to be able to search for spaces */
- X WaitTOF();
- X erase_frame();
- X tl = mx;
- X /* Find a space to the left... */
- X while (!IsSpace(tl, my)) {
- X tl -= fw;
- X if (tl < minx) {
- X break;
- X }
- X }
- X tl += fw;
- X tr = mx;
- X /* ...and to the right */
- X while (!IsSpace(tr, my)) {
- X tr += fw;
- X if (tr + fw > maxx) {
- X break;
- X }
- X }
- X tr -= fw;
- X if (tr < tl) {
- X tl = xl;
- X tr = xr;
- X }
- X}
- X
- X/* ChangeUnit cycles the unit of selection. The differents units
- X are: character, word and line.
- X*/
- X
- XVOID ChangeUnit()
- X{
- X
- X switch (Unit) {
- X case UNIT_FRAME: {
- X Unit = UNIT_CHAR;
- X break;
- X }
- X case UNIT_CHAR: {
- X Unit = UNIT_WORD;
- X FindWord();
- X xl = tl;
- X xr = tr;
- X break;
- X }
- X case UNIT_WORD: {
- X Unit = UNIT_LINE;
- X xl = minx;
- X xr = maxx;
- X break;
- X }
- X case UNIT_LINE: {
- X Unit = UNIT_FRAME;
- X xl = xr = mx;
- X break;
- X }
- X }
- X if (SnapRsrc->CrawlPtrn == 0) {
- X Ptrn = Pattern[Unit];
- X }
- X}
- X
- X/* ExtendSelection extends the current selection according to
- X the mouse position and the selected unit.
- X Note that ExtendSelection doesn't optimize moves that don't
- X make any difference. FIXME
- X*/
- X
- XVOID ExtendSelection()
- X{
- X /* Fix which row we're talking about */
- X if (closey == closetop) { /* Find closest row */
- X yt = my; /* change top row */
- X } else {
- X yb = my; /* change bottom row */
- X }
- X
- X /* Take care of left and right character pos */
- X switch (Unit) {
- X case UNIT_FRAME: {
- X if (closex == closeleft) {
- X xl = mx;
- X } else {
- X xr = mx;
- X }
- X break;
- X }
- X case UNIT_CHAR: {
- X if (yt == yb) { /* One line */
- X if (closex == closeleft) {
- X xl = mx;
- X } else {
- X xr = mx;
- X }
- X } else { /* Multiple lines */
- X if (yt == my) {
- X xl = mx; /* At top - set left */
- X } else {
- X xr = mx; /* At bottom - set right */
- X }
- X }
- X break;
- X }
- X case UNIT_WORD: {
- X FindWord(); /* Find the word */
- X if (yt == yb) { /* One line */
- X if (closex == closeleft) { /* Find closest char pos */
- X xl = tl;
- X } else {
- X xr = tr;
- X }
- X } else { /* Multiple lines */
- X if (yt == my) { /* Where am I */
- X xl = tl; /* At top - set left */
- X } else {
- X xr = tr; /* At bottom - set right */
- X }
- X }
- X break;
- X }
- X case UNIT_LINE: { /* Always full width */
- X break;
- X }
- X }
- X if (yt - fh == yb) {
- X yb += fh;
- X }
- X if (yt == yb && xl - fw == xr) {
- X xr += fw;
- X }
- X if (xr > maxx) { /* Check for window bounds */
- X xr = maxx;
- X }
- X if (xl < minx) { /* Check for window bounds */
- X xl = minx;
- X }
- X if (yb > maxy) { /* Check for window bounds */
- X yb = maxy;
- X }
- X}
- X
- X/* The actual character snapper. It actually works. :-) */
- X
- XWORD SnapChars()
- X{
- X LONG width;
- X LONG height;
- X UBYTE *SnapSpace;
- X ULONG SnapSize;
- X ULONG counter;
- X REGISTER LONG x, y;
- X
- X /* Check coordinates */
- X if (yt - fh == yb) { /* No rows, shouldn't happen */
- X return 0;
- X }
- X if (yt == yb && xl - fw == xr) { /* Nothing at all */
- X return 0;
- X }
- X
- X /* Calculate stuff */
- X width = maxx - (minx + 1) + fw + fw; /* Add one for a LF */
- X height = yb - yt + fh;
- X SnapSize = ((width / fw) + 1) * (height / fh);
- X counter = 0;
- X
- X /* Initialize things */
- X InitRastPort(&MyRP);
- X InitBitMap(&MyBM, 1L, width, height);
- X MyRP.BitMap = &MyBM;
- X SnapSpace = AllocMem(SnapSize, MEMF_PUBLIC|MEMF_CLEAR);
- X /* Please insert more memory */
- X if (!SnapSpace) {
- X return 0;
- X }
- X MyBM.Planes[0] = AllocRaster(width, height);
- X if (!MyBM.Planes[0]) {
- X FreeMem(SnapSpace, SnapSize);
- X return 0;
- X }
- X IFlags = 0;
- X /* Make a local copy of the snapped chars */
- X ClipBlit(&rp, minx, yt, &MyRP, 0L, 0L, width, height, COPY);
- X
- X /* Ok, now we've got a copy of the character data */
- X /* Now it's ok to mess with the layers again */
- X UnlockLayer(LockedLayer);
- X
- X /* Clear our work area */
- X BltClear((char *)TempRaster, 32L, 0L);
- X
- X /* Calculate bounds */
- X xl -= minx;
- X xr -= minx;
- X maxx -= minx;
- X minx = 0;
- X yb -= yt;
- X yt = 0;
- X
- X /* Single line - needs to be handled separately */
- X if (yt == yb) { /* Ok, we've got one */
- X
- X /* Read from left to right */
- X for (x = xl; x <= xr; x += fw, counter++) {
- X CopyChar(x, yt, COPY);
- X if ((SnapSpace[counter] = interpret(TempRaster)) == 255) {
- X SnapSpace[counter] = SnapRsrc->BadChar; /* Unrecognized */
- X }
- X }
- X if (Unit == UNIT_LINE) {
- X while (counter && SnapSpace[counter-1] == ' ') {
- X counter--;
- X }
- X }
- X } else { /* Multiple lines */
- X
- X if (Unit == UNIT_FRAME) {
- X minx = xl;
- X maxx = xr;
- X }
- X
- X /* Read first line */
- X for (x = xl; x <= maxx; x += fw, counter++) {
- X CopyChar(x, yt, COPY);
- X if ((SnapSpace[counter] = interpret(TempRaster)) == 255) {
- X SnapSpace[counter] = SnapRsrc->BadChar; /* Unrecognized */
- X }
- X }
- X if (Unit == UNIT_FRAME) {
- X SnapSpace[counter++] = 10;
- X } else {
- X SHORT endspace = (SnapSpace[counter-1] == ' ');
- X /* Remove trailing blanks */
- X while (counter && SnapSpace[counter-1] == ' ') {
- X counter--;
- X }
- X if (endspace || !(SnapRsrc->flags & JOINLONG)) {
- X SnapSpace[counter++] = 10;
- X }
- X }
- X
- X /* If more than two rows - read full middle rows */
- X if (yt + fh != yb) {
- X for (y = yt + fh; y < yb; y += fh) {
- X for (x = minx; x <= maxx; x += fw, counter++) {
- X CopyChar(x, y, COPY);
- X if ((SnapSpace[counter] = interpret(TempRaster)) == 255) {
- X SnapSpace[counter] = SnapRsrc->BadChar; /* Unrecognized */
- X }
- X }
- X if (Unit == UNIT_FRAME) {
- X SnapSpace[counter++] = 10;
- X } else {
- X SHORT endspace = (SnapSpace[counter-1] == ' ');
- X /* Remove trailing blanks */
- X while (counter && SnapSpace[counter-1] == ' ') {
- X counter--;
- X }
- X if (endspace || !(SnapRsrc->flags & JOINLONG)) {
- X SnapSpace[counter++] = 10;
- X }
- X }
- X }
- X }
- X
- X /* Read last line */
- X for (x = minx; x <= xr; x += fw, counter++) {
- X CopyChar(x, yb, COPY);
- X if ((SnapSpace[counter] = interpret(TempRaster)) == 255) {
- X SnapSpace[counter] = SnapRsrc->BadChar; /* Unrecognized */
- X }
- X }
- X /* Remove trailing blanks */
- X while (counter && SnapSpace[counter-1] == ' ') {
- X counter--;
- X }
- X }
- X FreeRaster(MyBM.Planes[0], width, height);
- X SaveClip(SnapSpace, counter);
- X FreeMem(SnapSpace, SnapSize);
- X return 1;
- X}
- X
- X
- X/* HandleChars is the part of the Snap state machine that handles
- X snapping of characters. The selection is done in different
- X units: char, word, line.
- X*/
- X
- XWORD HandleChars()
- X{
- X LONG xoff, yoff;
- X LONG ox, oy;
- X
- X /* Find out which screen we're working on */
- X theScreen = WhichScreen();
- X
- X /* Oops, no screen? */
- X if (!theScreen) {
- X action = noaction;
- X return 0;
- X }
- X
- X /* Ok, what window? */
- X window = WhichWindow(theScreen);
- X
- X /* Oh dear, no window. */
- X if (!window) {
- X action = noaction;
- X return 0;
- X }
- X
- X /* No messing with the layers while I think */
- X LockedLayer = window->WLayer;
- X LockLayer(0L, LockedLayer);
- X
- X /* Don't want to wreck somebody's rastport */
- X CopyMem((char *)window->RPort, (char *)&rp, (LONG)sizeof(struct RastPort));
- X
- X /* Or his picture */
- X SetDrMd(&rp, COMPLEMENT);
- X rp.Mask = SnapRsrc->FrameMask;
- X
- X /* Find out what we're trying to read */
- X SetSnapFont(rp.Font);
- X if (FontWidth == -1) {
- X UnlockLayer(LockedLayer);
- X action = noaction;
- X return 0;
- X }
- X
- X if (window->Flags & GIMMEZEROZERO) {
- X GZZ = 1;
- X } else {
- X GZZ = 0;
- X }
- X if (window->Flags & SUPER_BITMAP) {
- X SBM = 1;
- X } else {
- X SBM = 0;
- X }
- X
- X /* Find a position */
- X xl = (GZZ ? window->GZZMouseX : window->MouseX)
- X + window->RPort->Layer->Scroll_X;
- X yt = (GZZ ? window->GZZMouseY : window->MouseY)
- X + window->RPort->Layer->Scroll_Y;
- X
- X if (xl < 0) {
- X xl = 0;
- X }
- X if (yt < 0) {
- X yt = 0;
- X }
- X
- X /* Check your position */
- X if (xl > (GZZ ? window->GZZWidth : window->Width) ||
- X yt > (GZZ ? window->GZZHeight : window->Height)) {
- X UnlockLayer(LockedLayer);
- X action = noaction;
- X return 0;
- X }
- X IFlags = 0;
- X
- X /* Find out the offset for the clicked character, if any.
- X ** This is the part that makes it special. Simple, isn't it. Hah!
- X */
- X {
- X REGISTER struct CacheWindow *cw = GetCachedWindow(theScreen, window);
- X
- X if (cw) {
- X xoff = - ((xl - cw->xoff) % cw->fw);
- X yoff = - ((yt - cw->yoff) % cw->fh);
- X BltClear((char *)TempRaster, 32L, 0L);
- X ClipBlit(&rp, xl + xoff, yt + yoff,
- X &TempRp, 0L, 0L, (LONG)FontWidth, (LONG)FontHeight, COPY);
- X WaitBlit();
- X if (interpret(TempRaster) != 255) {
- X goto found;
- X }
- X }
- X /* No cache or cache didn't match */
- X xl -= 7;
- X yt -= 7;
- X BltClear((char *)TempRaster, 32L, 0L);
- X xoff = 0;
- X while (xoff < (16 - FontWidth)) {
- X ClipBlit(&rp, xl + xoff, yt,
- X &TempRp, 0L, 0L, (LONG)FontWidth, 16L, COPY);
- X WaitBlit();
- X yoff = 0;
- X while (yoff < (16 - FontHeight)) {
- X if (interpret(&TempRaster[yoff]) != 255) {
- X goto found;
- X }
- X ++yoff;
- X }
- X ++xoff;
- X }
- X
- X /* No character found. Back off */
- X UnlockLayer(LockedLayer);
- X action = noaction;
- X return 0;
- X
- Xfound:
- X /* Ok, now we know where to look for chars.
- X ** xoff and yoff is character position within our 16x16 bitmap.
- X */
- X xl = xl + xoff; /* Adjust x */
- X yt = yt + yoff; /* Adjust y */
- X
- X fw = FontWidth;
- X fh = FontHeight;
- X
- X {
- X SHORT temp = fh;
- X while (temp <= fh + 1) { /* Check for extra pixel row */
- X BltClear((char *)TempRaster, 32L, 0L);
- X ClipBlit(&rp, xl, yt + temp,
- X &TempRp, 0L, 0L, (LONG)FontWidth, (LONG)FontHeight, COPY);
- X WaitBlit();
- X if (interpret(TempRaster) != 255) {
- X fh = temp;
- X break;
- X }
- X ++temp;
- X }
- X }
- X
- X /* Find out offsets within the window */
- X xoff = xl % fw;
- X yoff = yt % fh;
- X
- X if (cw) {
- X cw->xoff = xoff;
- X cw->yoff = yoff;
- X cw->fw = fw;
- X cw->fh = fh;
- X } else {
- X CacheWindow(window, xoff, yoff, fw, fh);
- X }
- X }
- X
- X /* Set bounds */
- X minx = xoff;
- X maxx = minx +
- X (((GZZ ?
- X window->GZZWidth :
- X window->Width - window->BorderRight
- X /* Hack for borderless conman windows */
- X + (window->Flags & BORDERLESS && window->Flags & WINDOWSIZING ? 14 : 0))
- X - minx - fw) / fw) * fw;
- X maxy = ((GZZ ? window->GZZHeight : window->Height) / fh) * fh;
- X
- X /* Check bounds */
- X if (xl > maxx) {
- X UnlockLayer(LockedLayer);
- X action = noaction;
- X return 0;
- X }
- X /* Set box dimensions */
- X xr = xl;
- X yb = yt;
- X ox = xr;
- X oy = yt;
- X
- X /* Select unit while starting */
- X starting = 1;
- X
- X /* Starting unit is character or frame */
- X Unit = SnapRsrc->StartUnit;
- X Ptrn = (SnapRsrc->CrawlPtrn ? SnapRsrc->CrawlPtrn : Pattern[Unit]);
- X OFType = 0L;
- X update_frame();
- X
- X /* Get the state machine running */
- X FOREVER {
- X /* Wait for something to happen */
- X REGISTER LONGBITS sig =
- X Wait(movesignal|cancelsignal|donesignal|clicksignal|timersignal);
- X
- X if ((sig & timersignal) && (SnapRsrc->CrawlPtrn != 0xffff)) {
- X crawl_frame(0L);
- X }
- X
- X mx = (LONG)(GZZ ? window->GZZMouseX : window->MouseX)
- X + window->RPort->Layer->Scroll_X;
- X if (mx < 0) {
- X mx = 0;
- X }
- X /* Calculate which edge is closest */
- X if ((mx - xl) < (xr - mx)) {
- X closex = closeleft;
- X } else {
- X closex = closeright;
- X }
- X /* Only interested in real char pos */
- X mx = mx - ((mx - xoff) % fw);
- X
- X my = (LONG)(GZZ ? window->GZZMouseY : window->MouseY)
- X + window->RPort->Layer->Scroll_Y;
- X if (my < 0) {
- X my = 0;
- X }
- X /* Calculate which row is closest */
- X if ((my - yt) < (yb - my)) {
- X closey = closetop;
- X } else {
- X closey = closebottom;
- X }
- X my = my - ((my - yoff) % fh);
- X
- X /* Hey, it moves! It's alive!! */
- X if ((sig & movesignal) && (action == snaptext)) {
- X if (mx != ox || my != oy) { /* Something's happened */
- X ExtendSelection();
- X update_frame();
- X starting = 0;
- X ox = mx;
- X oy = my;
- X sig &= ~clicksignal;
- X }
- X }
- X
- X /* Ok, forget it... */
- X if (sig & cancelsignal) {
- X erase_frame();
- X UnlockLayer(LockedLayer);
- X return 0;
- X }
- X
- X /* Click */
- X if ((sig & clicksignal) && (action == snaptext)) {
- X /* Selecting unit */
- X if (starting) {
- X if (mx == ox && my == oy) {
- X ChangeUnit();
- X if (Unit == UNIT_CHAR) {
- X ChangeUnit();
- X }
- X update_frame();
- X } else if (Unit == UNIT_FRAME) {
- X ChangeUnit();
- X update_frame();
- X }
- X }
- X if (mx != ox || my != oy) { /* Click in a new place */
- X ExtendSelection();
- X update_frame();
- X starting = 0;
- X ox = mx;
- X oy = my;
- X }
- X }
- X
- X /* Finished */
- X if (sig & donesignal) {
- X erase_frame();
- X return SnapChars();
- X }
- X }
- X}
- X
- END_OF_FILE
- if test 21526 -ne `wc -c <'source/snapchars.c'`; then
- echo shar: \"'source/snapchars.c'\" unpacked with wrong size!
- fi
- # end of 'source/snapchars.c'
- fi
- echo shar: End of archive 3 \(of 4\).
- cp /dev/null ark3isdone
- MISSING=""
- for I in 1 2 3 4 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 4 archives.
- rm -f ark[1-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
- --
- Mail submissions (sources or binaries) to <amiga@cs.odu.edu>.
- Mail comments to the moderator at <amiga-request@cs.odu.edu>.
- Post requests for sources, and general dicussion to comp.sys.amiga.
-